﻿using PacketDotNet;
using SharpPcap;
using System;
using System.Collections.Generic;
using System.Diagnostics.Metrics;
using System.Text;
using System.Text.RegularExpressions;
using System.Linq;

namespace UTP
{
    public class Protocol : IDisposable
    {
        /// <summary>
        /// 设备列表
        /// </summary>
        private CaptureDeviceList devices;
        /// <summary>
        /// 通信对象
        /// </summary>
        protected ILiveDevice device = null;
        /// <summary>
        /// 释放标记
        /// </summary>
        private bool disposed;

        private object _lock = new object();

        private int badIndex = -1;
        /// <summary>
        /// 缓存包
        /// </summary>
        public Queue<byte[]> _rxb = new Queue<byte[]>();

        public List<byte> _raw = new List<byte>();

        public List<Package.Packet> _cache = new List<Package.Packet>();
        /// <summary>
        /// 接收消息回调
        /// </summary>
        public ReciveDelegate callback = null;
        /// <summary>
        /// 模式 false=发送 true=接收
        /// </summary>
        public bool Mode { get; set; }

        private PacketArrivalEventHandler arrivalEventHandler;
        /// <summary>
        /// 发送/接收处理线程
        /// </summary>
        private static Thread _thread;

        private object _locker = new object();

        private static Queue<Package.Packet> _queue=new Queue<Package.Packet>();
        /// <summary>
        /// 网卡工作模式
        /// </summary>
        private DeviceModes DeviceMode;

        public delegate void ReciveDelegate(byte[] buffer);
        public Protocol()
        {
            this.devices = CaptureDeviceList.Instance;
            //this.comm = new Comm();
        }
        ~Protocol() //析构函数
        {
            Dispose(false);
        }

        public class AppConfig
        {
            /// <summary>
            /// 设备序号
            /// </summary>
            public int DeviceIndex { get; set; }
            /// <summary>
            /// 工作模式
            /// </summary>
            public bool Mode { get; set; }
            /// <summary>
            /// 是否启用GZIP压缩
            /// </summary>
            public bool Gzip { get; set; }
        }
        /// <summary>
        /// 创建对象
        /// </summary>
        /// <param name="DeviceIndex">设备序号</param>
        /// <param name="Mode">工作模式 true=接收 false=发送</param>
        /// <param name="CallBack">消息回调</param>
        /// <param name="DeviceMode">设备工作模式</param>
        public void Connect(int DeviceIndex, bool Mode, ReciveDelegate CallBack,bool isZIP = false, DeviceModes DeviceMode = DeviceModes.DataTransferUdp)
        {
            this.device = devices[DeviceIndex];
            this.Mode = Mode;
            this.callback = CallBack;
            this.DeviceMode = DeviceMode;
            Package._zip = isZIP;
            
            if (this.Mode)//接收模式
            {
                
                device.Open( DeviceModes.Promiscuous);
                arrivalEventHandler = new PacketArrivalEventHandler(OnPacketArrival);
                device.OnPacketArrival += arrivalEventHandler;
                device.StartCapture();

                _thread = new Thread(_recive) { IsBackground = true };
                _thread.Start();
            }
            else
            {
                device.Open(this.DeviceMode);

                _thread = new Thread(_send) { IsBackground = true };
                _thread.Start();

            }
        }
        public void Dispose()
        {
            //必须为true
            Dispose(true);
            //通知垃圾回收器不再调用终结器
            GC.SuppressFinalize(this);
        }
        /// <summary>
        /// 非密封类可重写的Dispose方法，方便子类继承时可重写
        /// </summary>
        /// <param name="disposing"></param>
        protected virtual void Dispose(bool disposing)
        {
            if (disposed)
            {
                return;
            }
            //清理托管资源
            if (disposing)
            {
                
            }
            //清理非托管资源
            if (device != null)
            {
                if (!Mode)
                {
                    device.StopCapture();
                    device.OnPacketArrival -= arrivalEventHandler;
                }
                device.Close();
                device = null;
            }
            //告诉自己已经被释放
            disposed = true;
        }
        /// <summary>
        /// 获取设备列表
        /// </summary>
        /// <returns></returns>
        public string[] GetDeviceList()
        {
            Console.WriteLine("SharpPcap Version:{0}", Pcap.SharpPcapVersion);
            Regex r = new Regex("FriendlyName: .*\n"); //匹配连接的FriendlyName
            Match m;
            devices = CaptureDeviceList.Instance;
            var result = new List<string>();

            for(var i = 0; i < devices.Count; i++)
            {
                var _name = devices[i].ToString();
                m = r.Match(_name);
                result.Add(m.ToString());
            }

            return result.ToArray();
        }
        /// <summary>
        /// 发送UDP数据包
        /// </summary>
        /// <param name="str"></param>
        public void Send(string str)
        {
            Send(Encoding.UTF8.GetBytes(str));
        }
        /// <summary>
        /// 发送UDP数据包
        /// </summary>
        /// <param name="buffer"></param>
        public void Send(byte[] buffer)
        {
            var _splist = Package.Split(buffer);
            lock (_locker)
            {
                for (var i = 0; i < _splist.Count; i++)
                {
                    _queue.Enqueue(_splist[i]);
                }
            }

        }

        private void _send()
        {
            while (true)
            {
                while(_queue.Count > 0)
                {
                    lock (_locker)
                    {
                        var _packet = _queue.Dequeue();
                        if (_packet != null)
                        {
                            var _buffter = _packet.ToBytes();
                            device.SendPacket(_buffter);
                            //Thread.Sleep(0);
                        }
                    }
                    
                }
                Thread.Sleep(0);
            }
        }


        /// <summary>
        /// 后台线程处理
        /// </summary>
        private void _recive()
        {
            while (true)
            {
                while (_rxb.Count > 0)
                {
                    var _buffer = _rxb.Dequeue();
                    if (_buffer == null) break;
                    var _packet = new Package.Packet() { LoadData = _buffer };
                    if (_packet.Index == 0) { _cache.Clear(); badIndex = -1; }
                    if (!_packet.sucess)//坏包
                    {
                        badIndex = _packet.id;
                        continue;
                    }
                    if (badIndex == _packet.id) continue;//忽略掉
                    lock (_lock)
                    {
                        _cache.Add(_packet);
                    }
                    

                    if (_packet.Count == _packet.Index + 1)//终结符
                    {
                        var _data = Package.Combine(_cache);
                        _cache.Clear();
                        if(_data.Length == _packet.Size)
                            callback.Invoke(_data);
                    }
                }
                Thread.Sleep(1);
            }
        }

        /// <summary>
        /// 收到包数据
        /// </summary>
        /// <param name="s"></param>
        /// <param name="e"></param>
        private void OnPacketArrival(object s, PacketCapture e)
        {
            _rxb.Enqueue(e.Data.ToArray());
        }

    }
}
